#ifndef _RingQueue_HPP__
#define _RingQueue_HPP__

#include <iostream>
#include <pthread.h>
#include <vector>
#include "Sem.hpp"

#define g_default_capacity 20

template <class T>
class RingQueue
{
public:
    RingQueue(int default_num = g_default_capacity)
        :_ring_queue(default_num)
        ,_num(default_num)
        ,_c_step(0)
        ,_p_step(0)
        ,_space_sem(default_num)
        ,_data_sem(0)
    {
        pthread_mutex_init(&clock,nullptr);
        pthread_mutex_init(&plock,nullptr);

    }

    // 多生产多消费的意义在哪里？？你不要狭隘的认为，把任务或者数据放在交易场所，就是生产和消费啦
    // 将数据或者任务生产前和拿到之后处理，才是最耗费时间的。
    // 生产的本质：私有的任务-> 公共空间中
    // 消费的本质：公共空间中的任务-> 私有的

    // 信号量本质是一把计数器-> 计数器的意义是什么？？可以不用进入临界区，就可以得知资源情况，甚至可以减少临界区内部的判断！
    // 申请锁 -> 判断与访问 -> 释放锁 --> 本质是我们并不清楚临界资源的情况！！
    // 信号量要提前预设资源的情况，而且在pv变化过程中，我们可以在外部就能知晓临界资源的情况！

    void push(const T& in)//生产者
    {
        //先申请信号量再加锁，对标先买票再排队进公园，效率最高
        _space_sem.p();//生产等于消耗空间
        pthread_mutex_lock(&plock);
        _ring_queue[_p_step++] = in;
        _p_step %= _num;
        pthread_mutex_unlock(&plock);
        _data_sem.v();
    }

    void pop(T* out)//消费者
    {
        _data_sem.p();
        pthread_mutex_lock(&clock);
        *out = _ring_queue[_c_step++];
        _c_step %= _num;
        pthread_mutex_unlock(&clock);
        _space_sem.v();
    }

    // void debug()
    // {
    //     std::cerr << "size: " << _ring_queue.size() << " num: " << _num << std::endl;
    // }

    ~RingQueue()
    {
        pthread_mutex_destroy(&clock);
        pthread_mutex_destroy(&plock);
    }
private:
    std::vector<T> _ring_queue;
    int _num;
    int _c_step;//消费下标
    int _p_step;//生产下标
    Sem _space_sem;
    Sem _data_sem;
    pthread_mutex_t clock;//消费者锁
    pthread_mutex_t plock;//生产者锁
};

#endif